package com.kob.matchingsystem.service.impl.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

@Component
public class MatchingPool extends Thread {
    private static List<Player> players=new ArrayList<>();
    private final ReentrantLock lock=new ReentrantLock();

    private static RestTemplate restTemplate ;
    private final static String startGameUrl="http://backend-server:3000/pk/start/game/";

    @Autowired
    public void setRestTemplate(RestTemplate restTemplate) {
        MatchingPool.restTemplate=restTemplate;
    }

    public void addPlayer(Integer userId,Integer rating,Integer botId) {
        lock.lock();
        try{
            players.add(new Player(userId,rating,botId,0));
        }finally {
            lock.unlock();
        }
    }

    public void removePlayer(Integer userId) {
        lock.lock();
        try {
            List<Player> newPlayers = new ArrayList<>();//没有删的存下来
            for (Player player: players) {
                if (!player.getUserId().equals(userId)) {
                    newPlayers.add(player);
                }
            }
            players = newPlayers;
        } finally {
            lock.unlock();
        }
    }

    private void increaseWaitingTime() {//将所有玩家等待时间加1
        for (Player player: players) {
            player.setWaitingTime(player.getWaitingTime()+1);
        }
    }

    public boolean checkMatched(Player a, Player b) {//判断两名玩家是否匹配
        int ratingDelta=Math.abs(a.getRating()-b.getRating());
        int waitingTime=Math.min(a.getWaitingTime(),b.getWaitingTime());
        return ratingDelta<=waitingTime*10;
    }
    public void sendResult(Player a, Player b) {//返回匹配结果
        System.out.println("返回匹配结果:"+"a = " + a + ", b = " + b);

        MultiValueMap<String,String> data=new LinkedMultiValueMap<>();
        data.add("a_id",a.getUserId().toString());
        data.add("a_bot_id",a.getBotId().toString());
        data.add("b_id",b.getUserId().toString());
        data.add("b_bot_id",b.getBotId().toString());
        restTemplate.postForObject(startGameUrl,data,String.class);
    }

    public void matchPlayers() {//尝试匹配所有玩家
        boolean[] used=new boolean[players.size()];
        for(int i=0;i<players.size();i++) {
            if(used[i]) {continue;}//如果被匹配，continue
            for(int j=i+1;j<players.size();j++) {
                if(used[j]) {continue;}//如果被匹配，continue
                Player a=players.get(i);
                Player b=players.get(j);
                if(checkMatched(a,b)) {//判断a，b能不能匹配
                    used[i]=used[j]=true;//已经用过
                    sendResult(a,b);
                }
            }
        }
        List<Player> newPlayers=new ArrayList<>();
        for(int i=0;i<players.size();i++) {
            if(!used[i]) {
                newPlayers.add(players.get(i));
            }
        }
        players=newPlayers;
    }

    @Override
    public void run() {
        while(true) {
            try {
                Thread.sleep(1000);
                lock.lock();
                try{
                    increaseWaitingTime();
                    matchPlayers();
                }finally {
                    lock.unlock();
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }//对于线程的执行，我们期望周期性的执行，
    // 判断当前所有玩家中有没有匹配的。写一个死循环，Thread.sleep(1000)，
    // 每 1 秒中自动执行一遍。对于每一名玩家而言，每等待一秒，对应的waitingTime就会加一，
    // 相应的匹配阈值就会变大。
}
